/* ICMP parser */

/* Copyright (C) 2009-2011 David Zanetti
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */


#include <stdio.h>
#include <avr/io.h>
#include "global.h"
#include "string.h"
#include "encx24j600.h"
#include <util/delay.h>
#include "serial.h"
#include <avr/pgmspace.h>

typedef struct {
		uint8_t type;
		uint8_t code;
		uint8_t header_crc[2];
} icmp_header_t;
/* data payload is handled by other means */

uint16_t icmp_process(uint8_t slot,uint16_t len) {
	icmp_header_t pkt, tx;
	uint16_t crc;

	/* read our ICMP header */
	if (encx24j600_rx(&pkt,sizeof(icmp_header_t)) != sizeof(icmp_header_t)) {
#ifdef DEBUG_ICMP
		serial0_tx_PGM(PSTR("icmp; short frame, discarding\r\n"));
#endif
		return 0;
	}

	/* pkt now has our ICMP header payload, do something useful with it */
	if (pkt.type == 8 && pkt.code == 0) {
#ifdef DEBUG_ICMP
		serial0_tx_PGM(PSTR("icmp: echo request\r\n"));
#endif

		/* first prepend all the remaining data from the packet */
		crc = encx24j600_tx_crcdma_slot(slot,len-sizeof(icmp_header_t),0);

		/* type and code for echo reply for the header */
		tx.type = 0; /* Echo Reply */
		tx.code = 0;

		/* since our header is zeros, it doesn't materially affect CRC,
     just insert it into the header as-is */
		tx.header_crc[0] = crc & 0xff;
		tx.header_crc[1] = crc >> 8;

		/* then write the header */
		if (!encx24j600_tx_prepend(slot,(uint8_t *)&tx,sizeof(icmp_header_t))) {
			/* oops, well, life is hard */
			return 0;
		}

		return len; /* since we just echoed the data back! */
	}

	/* nothing we care about */
	return 0;
} 

